#pragma once
#include "exp_list.hpp"
#include "get_type.hpp"
#include <type_traits>
namespace exp_utilities {
    template<char c>
    struct exp_char { static constexpr char value = c; };

    namespace exp_str_detail {
        template<char ...str>
        struct exp_str_impl : exp_list<exp_char<str>...> {
            constexpr exp_str_impl() {}
            const char m_str[sizeof...(str)]{ str... };
            operator const char* () {
                return m_str;
            }
            static constexpr std::size_t length = sizeof...(str);
        };
        template<class TL> struct to_exp_char {};
        template<char ...str>
        struct to_exp_char<exp_list<exp_char<str>...>> {
            using type = exp_str_impl<str...>;
        };

        template<const char* p, class idx_ts>
        struct my_sptr_impl_conv;

        template<const char* p, std::size_t ...idx>
        struct my_sptr_impl_conv<p, std::index_sequence<idx...>>
        {
            using type = exp_str_detail::exp_str_impl<p[idx]...>;
        };

        template<std::size_t N, const char* p>
        struct my_sptr {
            static constexpr auto to_my_ch() {
                using cnt_arr = std::make_index_sequence<N>;
                using ret_t = typename my_sptr_impl_conv<p, cnt_arr>::type;
                return ret_t{};
            }
        };
        template<std::size_t N, const char* p>
        using meta_str = decltype(my_sptr<N, p>::to_my_ch());
    }
   
    template<class TL> using to_exp_char_t = get_type<exp_str_detail::to_exp_char<to_exp_list_t<TL>>>;

    template<std::size_t N>
    struct static_str {
        constexpr static_str(char const(&s)[N]) {
            std::ranges::copy(s, str);
        }
        char str[N];
    };

    template<static_str ss>
    constexpr auto operator ""_exp_str() {
        constexpr auto size = sizeof(ss.str);
        return exp_str_detail::meta_str<size, ss.str>{};
    }

    template<static_str ss>
    using str_to_list = typename exp_str_detail::meta_str<sizeof(ss.str), ss.str>::template to<exp_list>;
}